import { _decorator, Component, Node } from 'cc';
import BTTree from './Base/BTTree';
import MyTree from './Biz/Tree/MyTree';
import BTNode from './Base/BTNode';
import BTParent from './Base/BTParent';
import { NodeStatues } from './Enum';
const { ccclass, property } = _decorator;

@ccclass('BehaviorManager')
export class BehaviorManager extends Component {
    restartWhenComplete:boolean=true;
    tree:BTTree
    nodeList:Array<BTNode>=[];
    activeStack:Array<number>=[];
    parentIndex:Array<number>=[];
    childrenIndex:Array<Array<number>>=[];

    public start() {
        this.enableBehavior();
    }

    public restart(){
        this.pushNode(0);
    }
    public enableBehavior(){
        this.tree=new MyTree();
        this.parentIndex.push(-1);
        this.addToNodeList(this.tree.root);
        this.pushNode(0);
    }

    public addToNodeList(node:BTNode){
        this.nodeList.push(node);
        const index=this.nodeList.length-1;
        if(node instanceof BTParent){
            this.childrenIndex.push([])
            for(let i=0;i < node.children.length;i++){
                this.parentIndex.push(index);
                this.childrenIndex[index].push(this.nodeList.length);
                this.addToNodeList(node.children[i]);
            }
        }else {
            this.childrenIndex.push(null)
        }
    }

    protected update(dt: number): void {
        this.tick();
    }

    public tick(){
        let precvIndex=-1;
        let prevStatues=NodeStatues.Inactive;
        while(this.activeStack.length){
            const curIndex= this.activeStack.length-1;
            if(curIndex===precvIndex){
                break;
            }
            precvIndex=curIndex;
            prevStatues=this.runNode(this.activeStack[curIndex],prevStatues);
        }
    };

    public runNode(index:number,statues:NodeStatues):NodeStatues{
        this.pushNode(index);
        const node=this.nodeList[index];
        let statue=NodeStatues.Inactive;
        if(node instanceof BTParent){
            statue = this.runparentNdoe(index, statues);
        }else{
            statue=node.onUpdate();
        }

        if(statue!==NodeStatues.Running){
            this.popNode(index,statue);
        }
        return statue;
    };

    public runparentNdoe(index: number, statues: NodeStatues):NodeStatues{
        const node=this.nodeList[index] as BTParent;
        let childStatue = NodeStatues.Inactive;
        while (node.canExecute() && childStatue!== NodeStatues.Running) {
            childStatue =statues=this.runNode(this.childrenIndex[index][node.index],statues);
        }
        return statues
    };

    public pushNode(index:number){
        if(this.activeStack.length!==0&&this.activeStack[this.activeStack.length-1]===index){
            return;

        }
        this.activeStack.push(index);
        const node =this.nodeList[index];
        console.log(node,'pushNode node');
        node.onstart();
    };

    public popNode(index:number,statue:NodeStatues){
        this.activeStack.pop();
        const node=this.nodeList[index];
        node.onEnd();
        console.log(node,'popNode node');
        const parentIndex=this.parentIndex[index];
        if(parentIndex!==-1){
            const parentNode=this.nodeList[parentIndex] as BTParent;
            parentNode.onChildExecute(statue);
        }

        if(this.restartWhenComplete&&!this.activeStack.length){
            this.restart()
        }
    };
    // initTree() {
    //     this.tree=new MyTree();
    // }
    
    // update(){
    //     this.tree.root.run();
    // }
}


